// -*-mode:c++; coding:utf-8-*-

#ifndef _XBASE_IO_SERVICE_POOL_IMPL_HPP_
#define _XBASE_IO_SERVICE_POOL_IMPL_HPP_

#include "io_service_pool.hpp"

#include <boost/thread/thread.hpp>
#include <boost/foreach.hpp>

namespace xbase
{
	namespace impl
	{
		class single_io_service
			: public io_service_pool
		{
		private:
			typedef boost::thread thread;
			typedef boost::shared_ptr<thread> thread_ptr;
			
			typedef boost::asio::io_service io_service;
			typedef boost::shared_ptr<io_service> io_service_ptr;
			
			typedef io_service::work work;
			typedef boost::shared_ptr<work> work_ptr;

		public:
			single_io_service()
				: m_io_service()
				, m_work()
				, m_thread() {}

			virtual ~single_io_service() {
				// 按顺序删除
				m_thread.reset();
				m_work.reset();
				m_io_service.reset();
			}
			
			virtual void run() {
				m_io_service.reset(new io_service);
				m_work.reset(new work(*m_io_service));
				m_thread.reset(new thread(boost::bind(&io_service::run, m_io_service)));
			}
			
			virtual void stop() {
				m_io_service->stop();
			}
			
			virtual void join() {
				m_thread->join();
			}
			
		private:
			virtual
			boost::asio::io_service &get_1st_level_io_service() {
				return *m_io_service;
			}
			
			virtual
			boost::asio::io_service &get_2nd_level_io_service() {
				return *m_io_service;
			}
			
			virtual
			boost::asio::io_service &get_3rd_level_io_service() {
				return *m_io_service;
			}

		private:
			io_service_ptr m_io_service;
			work_ptr m_work;
			thread_ptr m_thread;
		};

		class one_io_service_per_level
			: public io_service_pool
		{
		private:
			typedef boost::thread thread;
			typedef boost::shared_ptr<thread> thread_ptr;
			
			typedef boost::asio::io_service io_service;
			typedef boost::shared_ptr<io_service> io_service_ptr;
			
			typedef io_service::work work;
			typedef boost::shared_ptr<work> work_ptr;

			static const std::size_t level_count = 3;
			
		public:
			one_io_service_per_level() {}

			virtual ~one_io_service_per_level() {
				// 按顺序删除
				m_threads.clear();
				m_works.clear();
				m_io_services.clear();
			}

			virtual void run() {
				for(std::size_t i = 0; i < level_count; ++i)
				{
					io_service_ptr s(new io_service);
					work_ptr w(new work(*s));
					thread_ptr t(new thread(boost::bind(&io_service::run, s)));

					m_io_services.push_back(s);
					m_works.push_back(w);
					m_threads.push_back(t);
				}
			}

			virtual void stop() {
				BOOST_FOREACH(io_service_ptr s, m_io_services)
				{
					s->stop();
				}
			}

			virtual void join() {
				BOOST_FOREACH(thread_ptr t, m_threads)
				{
					t->join();
				}
			}

		protected:
			virtual
			boost::asio::io_service &get_1st_level_io_service() {
				return *m_io_services[0];
			}
			
			virtual
			boost::asio::io_service &get_2nd_level_io_service() {
				return *m_io_services[1];
			}
			
			virtual
			boost::asio::io_service &get_3rd_level_io_service() {
				return *m_io_services[2];
			}


		private:
			std::vector<io_service_ptr> m_io_services;
			std::vector<work_ptr> m_works;
			std::vector<thread_ptr> m_threads;
		};

	} // namespace impl

} // namespace xbase

#endif	// _XBASE_IO_SERVICE_POOL_IMPL_HPP_
